import * as CANNON from '../libs/cannon-es.js';
import { CannonHelper } from '../libs/CannonHelper.js';
import { Ball } from './Ball.js';

const { PI, sin, cos, tan, min, max, abs } = Math
function addCannonHelper(body, color = 0xaaaaaa, helper, castShadow, receiveShadow) {
    if (!helper) { return };
    return helper.addVisual(body, color, castShadow, receiveShadow);
}

const defParams = () => ({
    position: { x: 0, y: 0, z: 0 },
    radius: Ball.RADIUS + .02,
    box_autowidth: false,
    box_width: 2,
    box_heigth: 5,
    thickness: 2,
    no_of_boxes: 5

})
class Arch { // 拱 
    constructor(params = {}) {
        this.body = new CANNON.Body({
            mass: 0,
            material: Table.FLOOR_MATERIAL
        });
        params = Object.assign(defParams(), params)

        this.position = params.position
        this.radius = params.radius
        this.box_autowidth = params.box_autowidth;
        this.box_height = params.box_height;
        this.box_width = params.box_width;
        this.box_thickness = params.box_thickness;
        this.no_of_boxes = params.no_of_boxes;

        this.body.position.set(params.position.x, params.position.y, params.position.z);
        const y_axis = new CANNON.Vec3(0, 1, 0);
        this.body.quaternion.setFromAxisAngle(y_axis, PI);

        const box_increment_angle = PI / (2 * this.no_of_boxes) //  inrement 增量
        let x_len = this.radius * tan(box_increment_angle);
        if (!this.box_autowidth) { x_len = this.box_width }

        const shape = new CANNON.Box(new CANNON.Vec3(x_len, this.box_height, this.thickness));
        for (let i = 0; i < this.no_of_boxes; i++) {
            const angle = box_increment_angle + (i * PI / this.no_of_boxes) //  全部黑照围成一个半圆， 在这个基础上加上 初相 increment
            let b_x = cos(angle), b_z = sin(angle);
            b_x *= this.radius + this.box_thickness;// 半径加厚度 那不就是最外面的
            b_z *= this.radius + this.box_thickness;// 半径加厚度 那不就是最外面的
            this.body.addShape(shape, new CANNON.Vec3(b_x, 0, b_z), params.helper.createQuaternionFromAxisAngle(y_axis, PI / 2 - angle)); // shape offset orientation
            // 就是 几何体 位置 旋转（四元数）

        }
    }
}

class Shorttwall {
    constructor(x, y, z, width) {
        const height = .02;
        const thickness = .04;
        this.body = new CANNON.Body({
            mass: 0,
            material: Table.WALL_MATERIAL
        })

        // How to make a mesh with a single triangle
        const vertices1 = [
            -0.125, height, -2 * thickness, // vertex 0
            0, height, 0,             // vertex 1
            0, height, -2 * thickness,   // vertex 2
            -0.125, -height, -2 * thickness,   // vertex 3
            0, -height, 0,             // vertex 4
            0, -height, -2 * thickness    // vertex 5
        ];

        // Corner of table
        const vertices2 = [
            0, height, -2 * thickness,  // vertex 0
            0, height, 0,              // vertex 1
            0.125, height, -2 * thickness,  // vertex 2
            0, -height, -2 * thickness,  // vertex 3
            0, -height, 0,              // vertex 4
            0.125, -height, -2 * thickness   // vertex 5
        ];

        const indices = [
            0, 1, 2,
            3, 4, 5,
            5, 0, 2,
            5, 3, 0,
            3, 4, 1,
            3, 1, 0,
            4, 5, 1,
            5, 2, 1
        ];


        const triemeshShape1 = new CANNON.Trimesh(vertices1, indices)
        const triemeshShape2 = new CANNON.Trimesh(vertices2, indices)
        this.body.position.set(x, y, z);

        this.body.addShape(triemeshShape1, new CANNON.Vec3(-width, 0, 0))
        this.body.addShape(triemeshShape2, new CANNON.Vec3(width, 0, 0))
        const boxShape = new CANNON.Box(new CANNON.Vec3(width, height, thickness));



        this.body.addShape(boxShape, new CANNON.Vec3(0, 0, -thickness))
        this.body.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), -PI / 2);
    }
}


class Longtwall {
    constructor(x, y, z, width) {
        const height = 0.02;
        const thickness = 0.025;

        this.body = new CANNON.Body({
            mass: 0, // mass == 0 makes the body static
            material: Table.WALL_MATERIAL
        });

        //adjust the x-coordinates to change the angle of the triangle shape
        const vertices1 = [
            -0.028, height, -2 * thickness, // vertex 0
            0, height, 0,             // vertex 1
            0, height, -2 * thickness, // vertex 2
            -0.028, -height, -2 * thickness, // vertex 3
            0, -height, 0,             // vertex 4
            0, -height, -2 * thickness  // vertex 5
        ];

        //corner of table
        const vertices2 = [
            0, height, -2 * thickness, // vertex 0
            0, height, 0,             // vertex 1
            0.08, height, -2 * thickness, // vertex 2
            0, -height, -2 * thickness, // vertex 3
            0, -height, 0,             // vertex 4
            0.08, -height, -2 * thickness  // vertex 5
        ];

        const indices = [
            0, 1, 2,
            5, 4, 3,
            5, 0, 2,
            5, 3, 0,
            3, 4, 1,
            3, 1, 0,
            4, 5, 1,
            5, 2, 1
        ];

        const triemeshShape1 = new CANNON.Trimesh(vertices1, indices)
        const triemeshShape2 = new CANNON.Trimesh(vertices2, indices)

        this.body.position.set(x, y, z);
        this.body.addShape(triemeshShape1, new CANNON.Vec3(-width, 0, 0))
        this.body.addShape(triemeshShape2, new CANNON.Vec3(width, 0, 0))

        const boxShape = new CANNON.Box(new CANNON.Vec3(width, height, thickness));

        this.body.addShape(boxShape, new CANNON.Vec3(0, 0, -thickness));

    }
}

class Hole {
    constructor(x, y, z, rotation, world, helper) {
        this.arch1 = new Arch({
            position: { x, y:y-.03, z },
            no_of_boxes: 6,
            box_height: .1,
            box_width: .025,
            box_autowidth: true,
            box_thickness: .01,
            helper
        })

        this.arch2 = new Arch({
            position: { x, y: y - .07, z },
            no_of_boxes: 6,
            box_height: .07,
            box_width: .025,
            box_autowidth: true,
            box_thickness: .01,
            helper
        })



        // 一半高一半矮凑成一个网洞  旋转角相差半圆
        this.arch1.body.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), PI - rotation);
        this.arch2.body.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), -rotation);

        world.addBody(this.arch1.body)
        world.addBody(this.arch2.body)

        window.debug  && addCannonHelper(this.arch1.body, 0x3333ff, helper,)
        //    obj1.name ='arch1'
        window.debug  && addCannonHelper(this.arch2.body, 0x33ffff, helper,)
        //    obj2.name='arch2'

        //    console.log(obj2, obj1 ,this.arch1);
    }


}



class Table {
    static LENGTH = 2.7432;
    static WIDTH = 1.3716;
    static HEIGHT = .06;
    static FLOOR_MATERIAL = new CANNON.Material('floorMaterial');
    static WALL_MATERIAL = new CANNON.Material('wallMaterial');
    static BOTTOm_MATERIAL = new CANNON.Material('bottomMaterial');
    constructor(game) {
        
        const helper = game.helper;
        this.world = game.world
        this.helper = helper;
        this.scene = game.scene;
        this.createRigitiBodies()
    }

    createRigitiBodies() {
        this.felt = this.createFelt();
        this.holes = this.createHoles();
        this.walls = this.createWalls();
        this.bottom = new CANNON.Body({
            shape: new CANNON.Plane(),
            mass: 0,
            material: Table.BOTTOm_MATERIAL,
            position: { x: 0, y: -.15, z: 0 },
            quaternion: new CANNON.Quaternion().setFromEuler(-Math.PI / 2, 0, 0)

        })
        this.world.addBody(this.bottom)
        window.debug  && addCannonHelper(this.bottom, 0xffff00, this.helper)

    }
    // 毛毡  所以现在就不需要之前那个长方体桌面了  毛毡作为桌面
    createFelt() {
        // 窄 带  窄带 
        const narrowStripWidth = .02;
        const narrowStripLength = Table.WIDTH / 2 - .05;
        const floorThickness = .01;
        const mainAreaX = Table.LENGTH / 2 - 2 * narrowStripWidth; // 内面积的长

        const floorBox = new CANNON.Box(new CANNON.Vec3(mainAreaX, floorThickness, Table.WIDTH / 2)) // 毛毡
        const floorBoxSmall = new CANNON.Box(new CANNON.Vec3(narrowStripWidth, floorThickness, narrowStripLength)) //

        const body = new CANNON.Body({
            mass: 0,
            material: Table.FLOOR_MATERIAL
        })

        body.addShape(floorBox, new CANNON.Vec3(0, -floorThickness, 0))
        body.addShape(floorBoxSmall, new CANNON.Vec3(-mainAreaX - narrowStripWidth, -floorThickness, 0))
        body.addShape(floorBoxSmall, new CANNON.Vec3(mainAreaX + narrowStripWidth, -floorThickness, 0))

        this.world.addBody(body)
        window.debug  &&  addCannonHelper(body, 0xFF00,this.helper, false, true )

    }
    createHoles() {
        const conner = { x: Table.LENGTH / 2 + .015, z: Table.WIDTH / 2 + .015, PIby4: PI / 4 }
        const middleZ = Table.WIDTH / 2 + .048;

        const holes = [
            new Hole(conner.x, 0, -conner.z, conner.PIby4, this.world, this.helper),
            new Hole(-conner.x, 0, -conner.z, -conner.PIby4, this.world, this.helper),

            new Hole(0, 0, -middleZ, 0, this.world, this.helper),
            new Hole(0, 0, middleZ, PI, this.world, this.helper),

            new Hole(conner.x, 0, conner.z, 3 * conner.PIby4, this.world, this.helper),
            new Hole(-conner.x, 0, conner.z, -3 * conner.PIby4, this.world, this.helper),

        ]
        console.log(this.helper);
        return holes;
    }
    createWalls() {
        const pos = { x: Table.LENGTH / 4 - .008, y: .02, z: Table.WIDTH / 2 };

        const wall1 = new Longtwall(pos.x, pos.y, -pos.z, .61);
        const wall2 = new Longtwall(-pos.x, pos.y, -pos.z, .61);
        wall2.body.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), PI);


        const wall3 = new Longtwall(pos.x, pos.y, pos.z, .61);
        const wall4 = new Longtwall(-pos.x, pos.y, pos.z, .61);
        wall3.body.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), PI);
        wall4.body.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), PI);

        //  球桌的长边是x 轴 短边是y轴
        const pos2 = { x: Table.LENGTH / 2 - .008, y: .02, z: 0 };

        const wall5 = new Shorttwall(pos2.x, pos.y, pos2.z, .605);
        const wall6 = new Shorttwall(-pos2.x, pos.y, pos2.z, .605);
        wall6.body.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), PI / 2); // 短边创建时就旋转过了



        const walls = [wall1, wall2, wall3, wall4, wall5, wall6];

        walls.forEach((wall) => {
            this.world.addBody(wall.body);
            window.debug  && addCannonHelper(wall.body, 0x00dd00,this.helper)

        })

        return walls
    }
}

export { Table }